package com.cnkvha.trackcontestmgmt.ui;

import com.cnkvha.trackcontestmgmt.TrackContestManagement;
import com.cnkvha.trackcontestmgmt.UserType;
import com.cnkvha.trackcontestmgmt.contest.Contest;
import com.cnkvha.trackcontestmgmt.contest.ContestState;
import com.cnkvha.trackcontestmgmt.ui.track.TrackInfoTableModel;
import com.cnkvha.trackcontestmgmt.ui.track.TrackTableCellRenderer;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;

public class ControlWindow extends JFrame {

    public ControlWindow() {
        setTitle("径赛裁判系统 by Kevin Wang");
        setSize(1200, 640);
        setExtendedState(MAXIMIZED_BOTH);

        setLayout(new BorderLayout());
        initComponents();
        initHandlers();

        // TEST ONLY
        // TrackContestManagement.instance.setCurrentContest(com.cnkvha.trackcontestmgmt.contest.Contest.readFromFile(new File("contests/Example.yml")));

        updateTimer.start();

        setVisible(true);
    }

    private boolean refresh = false;
    private Timer updateTimer = new Timer(100, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(refresh) {
                //lstContests.setModel(lstContests.getModel());
                //tblTracks.setModel(tblTracks.getModel());
                lstContests.invalidate();
                tblTracks.invalidate();
                ((TrackInfoTableModel) tblTracks.getModel()).fireTableDataChanged();
                refresh = false;
            }
            lstContests.repaint();

            tblTracks.repaint();
            updateOperationsPanel();
        }
    });

    public void markRefresh() {
        refresh = true;
    }

    private JSplitPane pnlParent;
    private JSplitPane pnlMainArea;

    private JSplitPane pnlLeft;
    private JSplitPane pnlLeftTop;
    private JScrollPane logAreaScrollPane;
    private JTextArea logArea;

    // buttons
    private JPanel pnlSessionManagementButtons;
    private JButton btnUpdatePassword;
    private JButton btnLoadNewContest;

    // contest list
    private JScrollPane pnlContests;
    private JList<Contest> lstContests;

    // operations
    private JSplitPane pnlOperations;
    private TrackInfoTableModel trackInfoTableModel;
    private JTable tblTracks;
    private JPanel pnlOperationsBottomPanel;

    private JPanel indicatorContestState;
    private JTextField textCurrentContestName;
    private JButton btnSetReady;
    private JButton btnSetStandby;


    private void initComponents() {
        pnlParent = new JSplitPane(JSplitPane.VERTICAL_SPLIT);

        // big title
        JLabel labelTitle = new JLabel("径赛裁判系统主控台", JLabel.CENTER);
        labelTitle.setSize(getWidth(), 50);
        labelTitle.setFont(new Font("微软雅黑", Font.BOLD, 42));
        add(labelTitle, BorderLayout.NORTH);
        pnlParent.setTopComponent(labelTitle);


        // main parent panel
        pnlMainArea = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        pnlMainArea.setResizeWeight(.12d);
        pnlParent.setBottomComponent(pnlMainArea);

        /* ======== panel left ======== */
        pnlLeft = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        pnlLeft.setResizeWeight(.8d);
        pnlMainArea.setLeftComponent(pnlLeft);
        logArea = new JTextArea();
        logArea.setEditable(false);
        logArea.setAutoscrolls(true);
        logArea.setLineWrap(true);
        logAreaScrollPane = new JScrollPane(logArea);
        logAreaScrollPane.setPreferredSize(new Dimension(200, 120));
        pnlLeft.setBottomComponent(logAreaScrollPane);

        /* ======== panel left: top ======== */
        pnlLeftTop = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        pnlLeft.setTopComponent(pnlLeftTop);

        pnlSessionManagementButtons = new JPanel();
        pnlSessionManagementButtons.setBackground(new Color(160, 185, 213));
        pnlSessionManagementButtons.setLayout(new GridLayout(1, 3));
        pnlLeftTop.setTopComponent(pnlSessionManagementButtons);

        btnUpdatePassword = new JButton("设置密码");
        pnlSessionManagementButtons.add(btnUpdatePassword, 0);

        btnLoadNewContest = new JButton("新赛事");
        pnlSessionManagementButtons.add(btnLoadNewContest, 1);

        /* ======== panel left top: bottom ======== */
        lstContests = new JList<>(new Contest[0]);
        pnlContests = new JScrollPane(lstContests);
        pnlLeftTop.setBottomComponent(pnlContests);
        lstContests.setDragEnabled(false);
        lstContests.setFixedCellHeight(24);

        /* ======== operations panel ======== */
        pnlOperations = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        pnlOperations.setResizeWeight(.6d);
        pnlMainArea.setRightComponent(pnlOperations);

        trackInfoTableModel = new TrackInfoTableModel();

        tblTracks = new JTable(trackInfoTableModel);
        tblTracks.setBackground(new Color(0xa0d0e0));
        tblTracks.setFont(new Font("微软雅黑", Font.BOLD, 24));
        tblTracks.setRowHeight(64);
        // stupid restrictions
        tblTracks.getColumnModel().getColumn(0).setWidth(64);
        tblTracks.getColumnModel().getColumn(0).setMinWidth(64);
        tblTracks.getColumnModel().getColumn(0).setMaxWidth(64);
        tblTracks.getColumnModel().getColumn(1).setWidth(64);
        tblTracks.getColumnModel().getColumn(1).setMinWidth(64);
        tblTracks.getColumnModel().getColumn(1).setMaxWidth(64);
        tblTracks.getColumnModel().getColumn(2).setWidth(180);
        tblTracks.getColumnModel().getColumn(2).setMinWidth(150);
        tblTracks.getColumnModel().getColumn(2).setMaxWidth(200);
        tblTracks.getColumnModel().getColumn(4).setWidth(48);
        tblTracks.getColumnModel().getColumn(4).setMinWidth(48);
        tblTracks.getColumnModel().getColumn(4).setMaxWidth(48);
        tblTracks.getColumnModel().getColumn(5).setWidth(72);
        tblTracks.getColumnModel().getColumn(5).setMinWidth(72);
        tblTracks.getColumnModel().getColumn(5).setMaxWidth(72);
        {
            for(int i = 0; i < tblTracks.getColumnModel().getColumnCount(); i++) {
                TableColumn col = tblTracks.getColumnModel().getColumn(i);
                col.setCellRenderer(new TrackTableCellRenderer());
            }
        }
        JScrollPane containerTableTracks = new JScrollPane(tblTracks);
        pnlOperations.setTopComponent(containerTableTracks);

        pnlOperationsBottomPanel = new JPanel();
        pnlOperationsBottomPanel.setLayout(new BoxLayout(pnlOperationsBottomPanel, BoxLayout.Y_AXIS));
        pnlOperationsBottomPanel.setBackground(new Color(0xDFFFC8));
        pnlOperations.setBottomComponent(pnlOperationsBottomPanel);

        {
            JLabel label = new JLabel("状态及控制面板");
            label.setAlignmentX(CENTER_ALIGNMENT);
            label.setFont(new Font("微软雅黑", 0, 48));
            pnlOperationsBottomPanel.add(label);
        }
        {
            Box box = Box.createHorizontalBox();

            indicatorContestState = new JPanel();
            indicatorContestState.setBackground(Color.RED);
            indicatorContestState.setPreferredSize(new Dimension(64, 64));
            indicatorContestState.setMaximumSize(indicatorContestState.getPreferredSize());
            box.add(indicatorContestState);

            JLabel labelCurrentContestName = new JLabel("赛事名称: ");
            labelCurrentContestName.setFont(new Font("微软雅黑", 0, 24));
            box.add(labelCurrentContestName);

            textCurrentContestName = new JTextField(TrackContestManagement.instance.isCurrentContestSet() ? TrackContestManagement.instance.getCurrentContest().name : "----");
            textCurrentContestName.setFont(new Font("微软雅黑", 0, 24));
            textCurrentContestName.setMaximumSize(new Dimension(Integer.MAX_VALUE, 28));
            textCurrentContestName.setEditable(false);
            box.add(textCurrentContestName);

            pnlOperationsBottomPanel.add(box);
        }
        {
            JPanel pnl = new JPanel(new GridLayout(1, 2));
            btnSetReady = new JButton("准备就绪"); pnl.add(btnSetReady, 0);
            btnSetStandby = new JButton("取消准备"); pnl.add(btnSetStandby,1);
            pnlOperationsBottomPanel.add(pnl);
        }

        pnlOperationsBottomPanel.add(Box.createVerticalGlue());

        add(pnlParent, BorderLayout.CENTER);
    }

    public void postInit() {
        lstContests.setCellRenderer(new ContestListRenderer());
        lstContests.setModel(new ContestListModel(TrackContestManagement.instance.getContestDataManager()));
        lstContests.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if(e.isAltDown() && e.getClickCount() == 2) {
                    Contest selected = lstContests.getSelectedValue();
                    if(selected != null) {
                        if(selected == TrackContestManagement.instance.getCurrentContest()) {
                            TrackContestManagement.log("已经加载了这个! ");
                            return;
                        }
                        if(TrackContestManagement.instance.setCurrentContest(selected)) {
                            TrackContestManagement.log("切换成功! ");
                        } else {
                            TrackContestManagement.log("切换失败! ");
                        }
                    }
                }
            }
        });
    }

    // update bottom displays and buttons
    public void updateOperationsPanel() {
        Contest current = TrackContestManagement.instance.getCurrentContest();
        if(current == null) {
            textCurrentContestName.setText("----");
            indicatorContestState.setBackground(Color.GRAY);
        } else {
            // current not null start
            textCurrentContestName.setText(current.name);

            if(System.currentTimeMillis() / 500%2 == 0) {
                indicatorContestState.setBackground(Color.BLACK);
            } else {
                Color c = current != null ? current.state.getIndicatorColor() : Color.MAGENTA;
                indicatorContestState.setBackground(c);
            }
            if(current.state == ContestState.STANDBY) {
                btnSetReady.setEnabled(true);
                btnSetStandby.setEnabled(false);
            } else if (current.state == ContestState.WAITING) {
                btnSetReady.setEnabled(false);
                btnSetStandby.setEnabled(true);
            } else {
                btnSetReady.setEnabled(false);
                btnSetStandby.setEnabled(false);
            }

            // current not null end
        }
    }

    private void initHandlers() {
        // update password
        btnUpdatePassword.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                PasswordChangeWindow w = new PasswordChangeWindow(ControlWindow.this);
                w.setVisible(true);
            }
        });
        btnLoadNewContest.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                JFileChooser fc = new JFileChooser();
                fc.setAcceptAllFileFilterUsed(false);
                fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
                fc.setFileFilter(new FileFilter() {
                    @Override
                    public boolean accept(File f) {
                        if(f.isDirectory()) return true;
                        return f.getName().toLowerCase().endsWith(".yml");
                    }

                    @Override
                    public String getDescription() {
                        return "";
                    }
                });
                fc.setMultiSelectionEnabled(true);
                int ret = fc.showOpenDialog(ControlWindow.this);
                if(ret == JFileChooser.APPROVE_OPTION) {
                    for(File f : fc.getSelectedFiles()) {
                        if(f.isFile()) {
                            TrackContestManagement.instance.getContestDataManager().tryLoadFile(f);
                        }
                    }
                }
            }
        });
        btnSetReady.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Contest contest = TrackContestManagement.instance.getCurrentContest();
                if(contest == null) return;
                if(contest.state == ContestState.STANDBY) {
                    TrackContestManagement.instance.queueOnOperationThread(() -> {
                        if(TrackContestManagement.instance.getWebSocketHandler().countUserType(UserType.BEGIN) <= 0) {
                            TrackContestManagement.log("[×] 无法开启比赛, 没有发令员! ");
                            return;
                        }
                        contest.state = ContestState.WAITING;
                        // broadcast and notify all clients
                        TrackContestManagement.instance.getWebSocketHandler().broadcastValidClients("state;" + ContestState.WAITING.name());
                        TrackContestManagement.log("比赛状态切换: [%s]", contest.state.getReadableName());
                    });
                } else {
                    TrackContestManagement.log("无法切换状态, 已经准备就绪, 等待发令了！");
                }
            }
        });
        btnSetStandby.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Contest contest = TrackContestManagement.instance.getCurrentContest();
                if(contest == null) return;
                if(contest.state == ContestState.WAITING) {
                    TrackContestManagement.instance.queueOnOperationThread(() -> {
                        contest.state = ContestState.STANDBY;
                        // broadcast and notify all clients
                        TrackContestManagement.instance.getWebSocketHandler().broadcastValidClients("state;" + ContestState.STANDBY.name());
                        TrackContestManagement.log("比赛状态切换: [%s]", contest.state.getReadableName());
                    });
                } else {
                    TrackContestManagement.log("无法切换状态, 已经是等待中了！");
                }
            }
        });
    }

    public synchronized void appendGUILog(String log) {
        logArea.append(log + "\n");
        JScrollBar sb = logAreaScrollPane.getVerticalScrollBar();
        sb.setValue(sb.getMaximum());
    }
}
